/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package practicadwh;

import basedatos.BackUp;
import basedatos.Conexion;
import basedatos.DDL;
import basedatos.DML;
import java.awt.Component;
import java.awt.Container;
import java.io.*;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JProgressBar;
import javax.swing.table.DefaultTableModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;

/**
 *
 * @author yojugracu
 */
public class AccionesPrincipal extends Thread {
    
    public AccionesPrincipal( Principal principal ){
        this.principal = principal;
        tablas = new Tablas();
    }            
    
    //-------------------- Se conecta a la base de datos ---------------------//
    public void conectar( String usuario, String password, String bd ){
        System.out.println( password );
        Conexion.setUsuario( usuario, password );
        connection = Conexion.getConexion( bd );
        
        principal.cboTablaHechos.removeAllItems();
        principal.getCboTiempo().removeAllItems();
        
        String[] tablas = DML.getTablas( connection );
        for( String tabla : tablas ){
            principal.cboTablaHechos.addItem(tabla);
            principal.getCboTiempo().addItem(tabla);
        }
        cargarTablas(tablas); arbolProyecto(tablas, "pro");
        setTablaHecho();
        this.user=usuario;
        this.password=password;
        this.base_datos=bd;
    }
    //------------------------------------------------------------------------//
    
    public void cargarTablas( String[] tables ){
        for( String tabla : tables ){
            ArrayList<String[]> campos = DML.getCamposTabla( connection, tabla );
            tablas.addTabla( tabla, new String[]{ "Llave", "Nombre", "Tipo", "Otro" } );
            tablas.addFilas( tabla, campos );
        }
    }
    
    //----------- Se agregan tablas para seleccionar cual sera de hecho ------//
    public void setTablaHecho(){
        String tabla = (String)principal.cboTablaHechos.getSelectedItem();
        principal.jtDatosTabla.setModel( tablas.getMTable( tabla ) );
        principal.jtMetricas.setName( tabla );
    }
    //------------------------------------------------------------------------//
    
    //------------------------------------------------------------------------//
    public DefaultListModel getTablas(){
        DefaultListModel dmlCbo = new DefaultListModel();
        String[] tablas = DML.getTablas( connection );
        for( String tabla : tablas ){
            dmlCbo.addElement( tabla );
        }
        return dmlCbo;
    }
    //------------------------------------------------------------------------//
    
    public String[] lista_tablas(){
        return DML.getTablas( connection );
    }
    
    
    public ArrayList<String[]> consulta(String sql){
        return DML.seleccionar(connection, sql);
    }
    
    
    //------------------- Agrega una metrica a la Tabla ----------------------//
    public void addMetrica(){
        int row = principal.jtDatosTabla.getSelectedRow();
        int column = principal.jtDatosTabla.getColumnCount();
        DefaultTableModel dtmDT = (DefaultTableModel)principal.jtDatosTabla.getModel();
        String[] fila = new String[ column ];

        for( int col = 0 ; col < column ; col++ ){
            
            fila[ col ] = (String)dtmDT.getValueAt( row, col );
        }
        DefaultTableModel dtmM = (DefaultTableModel)principal.jtMetricas.getModel();
        dtmM.addRow(fila);
    }
    //------------------------------------------------------------------------//
    
    //-------------------Agrega un campo calculado a la tabla de metricas seleccionadas-------
    
    public void add_campo_calculado(String [] fila){
        DefaultTableModel dtmM = (DefaultTableModel)principal.jtMetricas.getModel();
        dtmM.addRow(fila);
    }
    
    
    
    //-----------------------------------------------------------------------------------------
    
    
    //------------------- Elimina una metrica a la Tabla ----------------------//
    public void removeMetrica(){
        int row = principal.jtMetricas.getSelectedRow();
        DefaultTableModel dtmM = (DefaultTableModel)principal.jtMetricas.getModel();
        dtmM.removeRow( row );
    }
    //------------------------------------------------------------------------//
    
    ResultSet get_relaciones(String nom_tabla) {
         try {
            Statement stmt = connection.createStatement();
              ResultSet rs = stmt.executeQuery("SELECT pg_get_constraintdef(pg_constraint.oid) as definicion, pg_constraint.conname as nombrellave , pg_class.relname AS "
                      + "tabla,(select a.relname from pg_class a where a.oid=pg_constraint.confrelid) as "
                      + "tabla_foranea FROM pg_constraint, pg_class WHERE ((pg_constraint.contype = 'f'::\"char\") "
                      + "AND (pg_constraint.conrelid = pg_class.oid) and relname='"+nom_tabla+"')");
              return rs;
        } catch (SQLException ex) {
            Logger.getLogger(AccionesPrincipal.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
    
    public ArrayList get_campos(String nombre){
        return DML.getCamposTabla(connection,nombre);
    }

    public String getNombreBD()
    {

        return this.base_datos;
    }

    public boolean ejecutarScriptBD(String script,String db)
    {
        boolean exito=false;

        Connection connection2=this.crearConnection(user, password, db);
        progresando(20);
        exito=basedatos.DDL.ejecutarScript(connection2, script);
        progresando(90);
        try{
        connection2.close();
        exito=true;
        }catch(Exception e){e.printStackTrace();}

        //exito=basedatos.DDL.ejecutarScript(connection, script);
        progresando(100);
        return exito;
    }
    public Connection crearConnection(String usuario, String password,String bd)
    {
        Conexion.setUsuario( usuario, password );
        Connection con= Conexion.getConexion( bd );

        return con;
    }

    /**
     * Actualiza el listado de campos de la tabla seleccionada que contiene
     * el campo de la fecha.
     * @param tablaSeleccionada Indica la tabla que contiene el campo de fecha.
     */
    public void campoFecha(Object tablaSeleccionada){
        ArrayList<String[]> campos = DML.getCamposTabla( connection, (String)tablaSeleccionada);
        principal.getListaCampos().removeAllElements();
        for(String[] campo:campos)
            principal.getListaCampos().addElement(campo[1]);
    }

    public void crearProyecto( String usuario, String password, String servidor,
            String puerto, String bd, String uProyecto, String uBackUp, 
            Propiedades propiedades )
    { 
        
        Conexion.setUsuario( usuario, password );
        progresando(10);
        connection = Conexion.getConexion( servidor, puerto, "postgres" );
        DDL.crearBaseDatos(connection, bd);        
        
        progresando(20, "Realizando BackUp...");
        BackUp.restaurar( servidor, puerto, usuario, password, bd, uBackUp );
        
        try{ connection.close(); Thread.sleep(3000); }
        catch( Exception e ){ e.printStackTrace(); }
        progresando(60, "Conectando Nueva Base de datos ...");
        
        conectar(usuario, password, bd);
        progresando(90, "Creando Proyecto...");
        File file = new File( uProyecto, propiedades.getnProyecto() );
        propiedades.setPropiedadesBD(usuario, password, servidor, puerto, bd, file.getPath() );
        try{
            if( file.mkdirs() ) guardar( propiedades );
        }catch( Exception e ){ e.printStackTrace(); } progresando(100,"Finalizado");
    }
    
    public void guardar( Propiedades propiedades ){
        try{
            File f = new File( propiedades.getPath(), propiedades.getnProyecto() + ".dwh" );
            ObjectOutputStream salida = new ObjectOutputStream( 
                    new FileOutputStream( f ) );
            salida.writeObject( propiedades );
            salida.close();
        }catch( Exception e ){ e.printStackTrace(); }
    }
    
    public Propiedades abrir( String path ){
        try{
            ObjectInputStream entrada=new ObjectInputStream( 
                    new FileInputStream( path ) );
            
            Propiedades propiedades = (Propiedades)entrada.readObject();
            
            conectar( propiedades.getUsuario(), propiedades.getPassword(), 
                    propiedades.getBasedatos());
            
            DefaultTableModel dtm = propiedades.getMetricas();
            
            if( dtm != null ) principal.jtMetricas.setModel(dtm);
            
            
            return propiedades;
        }catch( Exception e ){ e.printStackTrace(); return null; }
    }
    
    public void arbolProyecto( String[] tables, String nombre ){
        DefaultMutableTreeNode proyecto = new DefaultMutableTreeNode( nombre );
        DefaultTreeModel tmodel = new DefaultTreeModel( proyecto );
        int i = 0;
        for( String hoja : tables )
        {
            DefaultMutableTreeNode hojat = new DefaultMutableTreeNode( hoja );
            tmodel.insertNodeInto(hojat, proyecto, i++);
            DefaultTableModel dtm = tablas.getMTable( hoja );
            
            for( int r = 0 ; r < dtm.getRowCount() ; r++ ){
                String valor = "";
                for( int c = 0 ; c < dtm.getColumnCount() - 1; c++ ){
                    String val = dtm.getValueAt(r, c).toString();
                    if( !val.equals("--") && c == 0 ){
                        valor += "pk ; ";
                    }
                    if( c > 0 ){
                        valor += val + " ; ";
                    }
                }
                DefaultMutableTreeNode dmtn = new DefaultMutableTreeNode( 
                        valor );
                tmodel.insertNodeInto(dmtn, hojat, r);
            }
        }

        DefaultTreeCellRenderer render = (DefaultTreeCellRenderer)principal.jtProyecto.getCellRenderer();
        render.setLeafIcon( new ImageIcon( getClass().getResource("/imagenes/row.png") )  );
        render.setOpenIcon( new ImageIcon( getClass().getResource("/imagenes/database_table.png") )  );
        render.setClosedIcon( new ImageIcon( getClass().getResource("/imagenes/database_table.png") )  );
        principal.jtProyecto.setModel(tmodel);
    }
    
    public void mensajeEspera( String descripcion ){
        /*MensajeEspera me = new MensajeEspera(principal);
        me.setDescripcion(descripcion);
        Thread t = new Thread(me);
        t.start();*/
        /*principal.lblMensajeProgreso.setText(descripcion);
        principal.jpbProgreso.setValue(0);
        principal.jdProgreso.setSize(300,100);
        principal.jdProgreso.setLocationRelativeTo(null);
        principal.jdProgreso.setAlwaysOnTop(true);
        principal.jdProgreso.setVisible(true);*/
    }
    
    public void run(){
        principal.jdProyecto.setVisible(false);
        principal.lblMensajeProgreso.setText(getDescripcion());
        principal.jpbProgreso.setValue(0);
        principal.jdProgreso.setSize(300,100);
        principal.jdProgreso.setLocationRelativeTo(null);
        principal.jdProgreso.setAlwaysOnTop(true);
        principal.jdProgreso.setVisible(true);
        switch( getOperacion() ){
            case 0:
                
                break;
        }
    }

    public byte getOperacion() {
        return operacion;
    }

    public void setOperacion(byte operacion) {
        this.operacion = operacion;
    }

    public String getDescripcion() {
        return descripcion;
    }

    public void setDescripcion(String descripcion) {
        this.descripcion = descripcion;
    }
    
    public void progresando( int val, String descripcion ){
        principal.jpbProgreso.setValue( val );
        principal.lblMensajeProgreso.setText(descripcion);
        principal.jpbProgreso.repaint();
    }
        
    public void progresando( int val ){
        principal.jpbProgreso.setValue( val );
        principal.jpbProgreso.repaint();
    }
    
    Connection connection;
    Principal principal;
    Tablas tablas;
    String user,password,base_datos;
    String descripcion;
    byte operacion;
}
